using System;
using System.Collections.Generic;
using System.Text;
using CommunityServer.Components;
using CommunityServer.Controls;
using CommunityServer.Discussions.Components;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.HtmlControls;
using TWC = Telligent.Glow;
using System.ComponentModel;
using System.IO;
using System.Collections.Specialized;
using System.Collections;
using CommunityServer.Discussions.Controls;
using CommunityServer;

namespace RobertMcLaws.CommunityServerStuff.Controls
{
    /// <summary>
    /// Form control that provides support for adding/editing ForumPosts.
    /// </summary>
    public class CreateEditForumPostForm : WrappedFormBase, ICallbackEventHandler, IDataItemsContainer
    {
        #region IDataItemsContainer

        public T GetDataItem<T>() where T : class
        {
            if (this.Forum is T)
                return this.Forum as T;
            else
                return null;
        }

        #endregion

        #region Child Controls

        protected Editor PostBodyEditor = null;
        protected TextBox PostSubjectTextBox = null;
        protected TextBox PostAuthorTextBox = null;
        protected IText ReplyToBodyText = null;
        protected IText ReplyToAuthorText = null;
        protected TextBox EditNotesBodyTextBox = null;
        protected TextBox CurrentEditNotesTextBox = null;
        protected DropDownList PinnedPostDropDownList;
        protected CheckBox IsLockedCheckBox;
        protected CheckBox SubscribeToThreadCheckBox;
        protected CheckBox IsAnonymousPostCheckBox;
        protected ForumPostList PreviewForumPostList;
        protected RadioButtonList PostIconRadioButtonList;
        protected IButton SubmitButton;
        protected IButton QuoteButton;
        protected IText RecipientsText;

        protected List<WrappedSubFormBase> SubForms;

        #endregion

        #region Properties

        /// <summary>
        /// Gets or sets the unmoderated success actions.
        /// </summary>
        /// <value>The unmoderated success actions.</value>
        [
        Browsable(false),
        DefaultValue(null),
        Description("Defines the action to take after the form is processed successfully"),
        PersistenceMode(PersistenceMode.InnerProperty),
        ]
        public virtual Actions UnmoderatedSuccessActions
        {
            get { return _unmoderatedSuccessActions; }
            set
            {
                if (_unmoderatedSuccessActions != null)
                    this.Controls.Remove(_unmoderatedSuccessActions);

                _unmoderatedSuccessActions = value;
                if (_unmoderatedSuccessActions != null)
                    this.Controls.Add(_unmoderatedSuccessActions);
            }
        }
        private Actions _unmoderatedSuccessActions;

        /// <summary>
        /// Gets or sets the moderated success actions.
        /// </summary>
        /// <value>The moderated success actions.</value>
        [
        Browsable(false),
        DefaultValue(null),
        Description("Defines the action to take after the form is processed successfully"),
        PersistenceMode(PersistenceMode.InnerProperty),
        ]
        public virtual Actions ModeratedSuccessActions
        {
            get { return _moderatedSuccessActions; }
            set
            {
                if (_moderatedSuccessActions != null)
                    this.Controls.Remove(_moderatedSuccessActions);

                _moderatedSuccessActions = value;
                if (_moderatedSuccessActions != null)
                    this.Controls.Add(_moderatedSuccessActions);
            }
        }
        private Actions _moderatedSuccessActions;

        /// <summary>
        /// Gets or sets the post body Editor id.
        /// </summary>
        /// <value>The post body Editor id.</value>
        public string PostBodyEditorId
        {
            get { return ((string)ViewState["PostBodyEditorId"]) ?? string.Empty; }
            set { ViewState["PostBodyEditorId"] = value; }
        }

        /// <summary>
        /// Gets or sets the post subject TextBox id.
        /// </summary>
        /// <value>The post subject TextBox id.</value>
        public string PostSubjectTextBoxId
        {
            get { return ((string)ViewState["PostSubjectTextBoxId"]) ?? string.Empty; }
            set { ViewState["PostSubjectTextBoxId"] = value; }
        }

        /// <summary>
        /// Gets or sets the pinned post DropDownList id.
        /// </summary>
        /// <value>The pinned post DropDownList id.</value>
        public string PinnedPostDropDownListId
        {
            get { return ((string)ViewState["PinnedPostDropDownListId"]) ?? string.Empty; }
            set { ViewState["PinnedPostDropDownListId"] = value; }
        }

        /// <summary>
        /// Gets or sets the locked CheckBox id.
        /// </summary>
        /// <value>The locked CheckBox id.</value>
        public string IsLockedCheckBoxId
        {
            get { return ((string)ViewState["IsLockedCheckBoxId"]) ?? string.Empty; }
            set { ViewState["IsLockedCheckBoxId"] = value; }
        }

        /// <summary>
        /// Gets or sets the subscribe to thread CheckBox id.
        /// </summary>
        /// <value>The subscribe to thread CheckBox id.</value>
        public string SubscribeToThreadCheckBoxId
        {
            get { return ((string)ViewState["SubscribeToThreadCheckBoxId"]) ?? string.Empty; }
            set { ViewState["SubscribeToThreadCheckBoxId"] = value; }
        }

        /// <summary>
        /// Gets or sets the anonymous post CheckBox id.
        /// </summary>
        /// <value>The is anonymous post CheckBox id.</value>
        public string IsAnonymousPostCheckBoxId
        {
            get { return ((string)ViewState["IsAnonymousPostCheckBoxId"]) ?? string.Empty; }
            set { ViewState["IsAnonymousPostCheckBoxId"] = value; }
        }

        /// <summary>
        /// Gets or sets the post icon RadioButtonList id.
        /// </summary>
        /// <value>The post icon RadioButtonList id.</value>
        public string PostIconRadioButtonListId
        {
            get { return ((string)ViewState["PostIconRadioButtonListId"]) ?? string.Empty; }
            set { ViewState["PostIconRadioButtonListId"] = value; }
        }

        /// <summary>
        /// Gets or sets the preview ForumPostList id.
        /// </summary>
        /// <value>The preview ForumPostList id.</value>
        public string PreviewForumPostListId
        {
            get { return ((string)ViewState["PreviewForumPostListId"]) ?? string.Empty; }
            set { ViewState["PreviewForumPostListId"] = value; }
        }

        /// <summary>
        /// Gets or sets the submit IButton id.
        /// </summary>
        /// <value>The submit IButton id.</value>
        public string SubmitButtonId
        {
            get { return ((string)ViewState["SubmitButtonId"]) ?? string.Empty; }
            set { ViewState["SubmitButtonId"] = value; }
        }

        /// <summary>
        /// Gets or sets the comma-separated list of sub-form ids.
        /// </summary>
        /// <value>The sub-form ids.</value>
        public string SubFormIds
        {
            get { return ((string)ViewState["SubFormIds"]) ?? string.Empty; }
            set { ViewState["SubFormIds"] = value; }
        }

        /// <summary>
        /// Gets or sets the reply to body IText id.
        /// </summary>
        /// <value>The reply to body IText id.</value>
        public string ReplyToBodyTextId
        {
            get { return ((string)ViewState["ReplyToBodyTextId"]) ?? string.Empty; }
            set { ViewState["ReplyToBodyTextId"] = value; }
        }

        /// <summary>
        /// Gets or sets the reply to author IText id.
        /// </summary>
        /// <value>The reply to author IText id.</value>
        public string ReplyToAuthorTextId
        {
            get { return ((string)ViewState["ReplyToAuthorTextId"]) ?? string.Empty; }
            set { ViewState["ReplyToAuthorTextId"] = value; }
        }

        /// <summary>
        /// Gets or sets the edit notes body TextBox id.
        /// </summary>
        /// <value>The edit notes body TextBox id.</value>
        public string EditNotesBodyTextBoxId
        {
            get { return ((string)ViewState["EditNotesBodyTextBoxId"]) ?? string.Empty; }
            set { ViewState["EditNotesBodyTextBoxId"] = value; }
        }

        /// <summary>
        /// Gets or sets the current edit notes TextBox id.
        /// </summary>
        /// <value>The current edit notes TextBox id.</value>
        public string CurrentEditNotesTextBoxId
        {
            get { return ((string)ViewState["CurrentEditNotesTextBoxId"]) ?? string.Empty; }
            set { ViewState["CurrentEditNotesTextBoxId"] = value; }
        }

        /// <summary>
        /// Gets or sets the quote IButton id.
        /// </summary>
        /// <value>The quote IButton id.</value>
        public string QuoteButtonId
        {
            get { return ((string)ViewState["QuoteButtonId"]) ?? string.Empty; }
            set { ViewState["QuoteButtonId"] = value; }
        }

        /// <summary>
        /// Gets or sets the edit notes validation group.
        /// </summary>
        /// <value>The edit notes validation group.</value>
        public string EditNotesValidationGroup
        {
            get { return ((string)ViewState["EditNotesValidationGroup"]) ?? string.Empty; }
            set { ViewState["EditNotesValidationGroup"] = value; }
        }

        /// <summary>
        /// Gets or sets the recipients IText id.
        /// </summary>
        /// <value>The recipients IText id.</value>
        public string RecipientsTextId
        {
            get { return ((string)ViewState["RecipientsTextId"]) ?? string.Empty; }
            set { ViewState["RecipientsTextId"] = value; }
        }

        private ForumPost _forumPost = null;
        public override object DataSource
        {
            get
            {
                if (_forumPost == null)
                    _forumPost = ForumControlUtility.Instance().GetCurrentForumPost(this);

                return _forumPost;
            }
            set
            {
                if (value is ForumPost)
                    _forumPost = value as ForumPost;
                else
                    throw new InvalidCastException("DataSource must be a valid ForumPost object");
            }
        }

        private Forum _forum = null;
        /// <summary>
        /// Gets or sets the Forum.
        /// </summary>
        /// <value>The forum.</value>
        public virtual Forum Forum
        {
            get
            {
                if (_forum == null)
                {
                    if (this.DataSource != null)
                        _forum = ((ForumPost)this.DataSource).Forum;
                    else if (this.ReplyToPost != null)
                        _forum = ReplyToPost.Forum;
                    else if (this.Recipient != null)
                        _forum = Forums.GetForum(0);
                    else
                        _forum = ForumControlUtility.Instance().GetCurrentForum(this);
                }

                return _forum;
            }
            set
            {
                _forum = value as Forum;
            }
        }

        private ForumPost _replyToforumPost = null;
        /// <summary>
        /// Gets or sets the reply to ForumPost.
        /// </summary>
        /// <value>The reply to post.</value>
        public virtual ForumPost ReplyToPost
        {
            get
            {
                if (_replyToforumPost == null)
                    _replyToforumPost = ForumControlUtility.Instance().GetCurrentParentForumPost(this);

                return _replyToforumPost;
            }
            set
            {
                _replyToforumPost = value as ForumPost;
            }
        }

        /// <summary>
        /// Gets the name of the reply to post author.
        /// </summary>
        /// <value>The name of the reply to post author.</value>
        public virtual string ReplyToPostAuthorName
        {
            get
            {
                if (ReplyToPost != null)
                {
                    if (ReplyToPost.IsAnonymousPost && ForumConfiguration.Instance().EnableUserPostingAsAnonymous && ReplyToPost.Forum.EnableAnonymousPostingForUsers)
                        return ResourceManager.GetString("DefaultAnonymousUsername");
                    else
                        return ReplyToPost.User.DisplayName;
                }
                else
                    return string.Empty;
            }
        }

        private User _recipient = null;
        /// <summary>
        /// Gets or sets the recipient.
        /// </summary>
        /// <value>The recipient.</value>
        public virtual User Recipient
        {
            get
            {
                if (_recipient == null && this.ReplyToPost != null)
                    _recipient = this.ReplyToPost.User;

                if (_recipient == null)
                {
                    CSContext csContext = ForumControlUtility.Instance().GetCurrentCSContext(this.Page);
                    if (this.DataSource != null)
                    {
                        HybridDictionary recipients = PrivateMessages.GetRecipients(((ForumPost)this.DataSource).ThreadID, csContext.User.UserID);
                        foreach (int userID in recipients.Keys)
                        {
                            _recipient = Users.GetUser(userID, false);
                            break;
                        }
                    }

                    if (_recipient == null && this.ReplyToPost != null)
                    {
                        HybridDictionary recipients = PrivateMessages.GetRecipients(this.ReplyToPost.ThreadID, csContext.User.UserID);
                        foreach (int userID in recipients.Keys)
                        {
                            _recipient = Users.GetUser(userID, false);
                            break;
                        }
                    }

                    if (_recipient == null && this.DataSource != null)
                        _recipient = PrivateMessages.GetOriginalRecipient((ForumPost)this.DataSource);

                    if (_recipient == null && this.DataSource != null)
                        _recipient = ((ForumPost)this.DataSource).User;

                    if (_recipient == null && csContext.UserID > 0)
                        _recipient = Users.GetUser(csContext.UserID, false);
                }

                return _recipient;
            }
            set
            {
                _recipient = value as User;
            }
        }

        #endregion

        #region Form Overrides

        protected override void AddPropertyControls()
        {
            if (this.UnmoderatedSuccessActions != null)
                this.Controls.Add(this.UnmoderatedSuccessActions);

            if (this.ModeratedSuccessActions != null)
                this.Controls.Add(this.ModeratedSuccessActions);

            base.AddPropertyControls();
        }

        protected override void AttachChildControls()
        {
            PostBodyEditor = ForumControlUtility.Instance().FindControl(this, PostBodyEditorId) as Editor;
            PostSubjectTextBox = ForumControlUtility.Instance().FindControl(this, PostSubjectTextBoxId) as TextBox;
            PinnedPostDropDownList = ForumControlUtility.Instance().FindControl(this, PinnedPostDropDownListId) as DropDownList;
            IsLockedCheckBox = ForumControlUtility.Instance().FindControl(this, IsLockedCheckBoxId) as CheckBox;
            SubscribeToThreadCheckBox = ForumControlUtility.Instance().FindControl(this, SubscribeToThreadCheckBoxId) as CheckBox;
            IsAnonymousPostCheckBox = ForumControlUtility.Instance().FindControl(this, IsAnonymousPostCheckBoxId) as CheckBox;
            PreviewForumPostList = ForumControlUtility.Instance().FindControl(this, PreviewForumPostListId) as ForumPostList;
            PostIconRadioButtonList = ForumControlUtility.Instance().FindControl(this, PostIconRadioButtonListId) as RadioButtonList;
            SubmitButton = ForumControlUtility.Instance().FindButtonControl(this, SubmitButtonId);
            ReplyToBodyText = ForumControlUtility.Instance().FindTextControl(this, ReplyToBodyTextId);
            ReplyToAuthorText = ForumControlUtility.Instance().FindTextControl(this, ReplyToAuthorTextId);
            EditNotesBodyTextBox = ForumControlUtility.Instance().FindControl(this, EditNotesBodyTextBoxId) as TextBox;
            CurrentEditNotesTextBox = ForumControlUtility.Instance().FindControl(this, CurrentEditNotesTextBoxId) as TextBox;
            QuoteButton = ForumControlUtility.Instance().FindButtonControl(this, QuoteButtonId);
            RecipientsText = ForumControlUtility.Instance().FindTextControl(this, RecipientsTextId);

            if (PostBodyEditor == null
                || PostSubjectTextBox == null
                || SubmitButton == null)
                throw new InvalidOperationException("PostBodyEditorId, PostSubjectTextBoxId and SubmitButtonId must be valid controls to render a CreateEditForumPostForm");

            Forum forum = ForumControlUtility.Instance().GetCurrentForum(this);
            CSContext csContext = ForumControlUtility.Instance().GetCurrentCSContext(this.Page);
            if (PinnedPostDropDownList != null && forum != null)
            {
                string selectedValue = PinnedPostDropDownList.SelectedValue;

                PinnedPostDropDownList.Items.Clear();
                PinnedPostDropDownList.Items.Add(new ListItem(ResourceManager.GetString("CreateEditPost_Sticky_0"), "0"));
                PinnedPostDropDownList.Items.Add(new ListItem(ResourceManager.GetString("CreateEditPost_Sticky_1"), "1"));
                PinnedPostDropDownList.Items.Add(new ListItem(ResourceManager.GetString("CreateEditPost_Sticky_3"), "3"));
                PinnedPostDropDownList.Items.Add(new ListItem(ResourceManager.GetString("CreateEditPost_Sticky_7"), "7"));
                PinnedPostDropDownList.Items.Add(new ListItem(ResourceManager.GetString("CreateEditPost_Sticky_14"), "14"));
                PinnedPostDropDownList.Items.Add(new ListItem(ResourceManager.GetString("CreateEditPost_Sticky_30"), "30"));
                PinnedPostDropDownList.Items.Add(new ListItem(ResourceManager.GetString("CreateEditPost_Sticky_90"), "90"));
                PinnedPostDropDownList.Items.Add(new ListItem(ResourceManager.GetString("CreateEditPost_Sticky_180"), "180"));
                PinnedPostDropDownList.Items.Add(new ListItem(ResourceManager.GetString("CreateEditPost_Sticky_360"), "366"));

                if (csContext.User.IsForumAdministrator
                    || Permissions.ValidatePermissions(forum, Permission.Announcement, csContext.User)
                    || Moderate.CheckIfUserIsModerator(csContext.User.UserID, forum.SectionID))
                    PinnedPostDropDownList.Items.Add(new ListItem(ResourceManager.GetString("CreateEditPost_Sticky_999"), "999"));

                if (!string.IsNullOrEmpty(selectedValue) && PinnedPostDropDownList.Items.FindByValue(selectedValue) != null)
                    PinnedPostDropDownList.SelectedValue = selectedValue;

                PinnedPostDropDownList.AutoPostBack = true;
                PinnedPostDropDownList.SelectedIndexChanged += new EventHandler(PinnedPostDropDownList_SelectedIndexChanged);
            }

            if (PostIconRadioButtonList != null)
            {
                string selectedValue = PostIconRadioButtonList.SelectedValue;

                PostIconRadioButtonList.Items.Clear();
                PostIconRadioButtonList.Items.Add(new ListItem(ResourceManager.GetString("None"), ""));
                foreach (Smiley smiley in Smilies.GetSmilies(true))
                {
                    if (smiley != null)
                        PostIconRadioButtonList.Items.Add(new ListItem(string.Format("<img src=\"{0}{1}\" alt=\"{2}\" />", Globals.GetSiteUrls().Emoticon, smiley.SmileyUrl, smiley.SmileyText + " [" + smiley.SmileyCode + "]"), smiley.SmileyId.ToString()));
                }

                if (!string.IsNullOrEmpty(selectedValue) && PostIconRadioButtonList.Items.FindByValue(selectedValue) != null)
                    PostIconRadioButtonList.SelectedValue = selectedValue;
            }

            SubmitButton.Click += new EventHandler(SubmitButton_Click);

            this.SubForms = new List<WrappedSubFormBase>();
            if (!string.IsNullOrEmpty(this.SubFormIds))
            {
                foreach (string id in this.SubFormIds.Split(','))
                {
                    WrappedSubFormBase subForm = ForumControlUtility.Instance().FindControl(this, id) as WrappedSubFormBase;
                    if (subForm != null)
                    {
                        subForm.HostForm = this;
                        this.SubForms.Add(subForm);
                    }
                }
            }

            if (PreviewForumPostList != null)
            {
                PreviewForumPostList.DataSource = new List<ForumPost>();

                if (PreviewForumPostList.Tag == WrappedControlTag.Unknown)
                    PreviewForumPostList.Tag = WrappedControlTag.Div;

                if (string.IsNullOrEmpty(PreviewForumPostList.ContainerId))
                    PreviewForumPostList.ContainerId = PreviewForumPostList.ClientID;
            }
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            if (this.QuoteButton != null && this.QuoteButton.Visible)
                Telligent.Glow.ClientScripts.RegisterScriptsForCommon(this);
        }

        #endregion

        #region Data Binding

        public override void DataBind()
        {
            base.DataBind();

            ForumPost post = DataSource as ForumPost;
            ForumPost replyToPost = ReplyToPost;
            Forum forum = this.Forum;
            CSContext csContext = ForumControlUtility.Instance().GetCurrentCSContext(this.Page);

            if (forum == null)
            {
                this.AutomatedVisible = false;
                return;
            }

            AccessCheck(forum, csContext.User, post, replyToPost);

            #region Data binding (performed when not a postback and with a post)

            if (!Page.IsPostBack && post != null)
            {
                PostBodyEditor.Text = post.Body;
                PostSubjectTextBox.Text = Globals.HtmlDecode(post.Subject);

                if (CurrentEditNotesTextBox != null)
                    CurrentEditNotesTextBox.Text = post.EditNotes;

                if (PinnedPostDropDownList != null)
                {
                    #region Determine Value of PinnedPostDropDownList

                    Thread thread = Threads.GetThread(post.ThreadID);
                    if (thread != null && thread.IsSticky)
                    {
                        // Get time span for 2 years
                        TimeSpan anouncementTsp = (DateTime.Now - DateTime.Now.AddYears(-2));

                        TimeSpan remainder = thread.StickyDate.Subtract(DateTime.Now);

                        // The check is +1 day, since it is set for midnight and can sometimes be up to one day extra
                        if (remainder <= TimeSpan.FromDays(2))
                            PinnedPostDropDownList.Items.FindByValue("1").Selected = true;
                        else if (remainder <= TimeSpan.FromDays(4))
                            PinnedPostDropDownList.Items.FindByValue("3").Selected = true;
                        else if (remainder <= TimeSpan.FromDays(8))
                            PinnedPostDropDownList.Items.FindByValue("7").Selected = true;
                        else if (remainder <= TimeSpan.FromDays(15))
                            PinnedPostDropDownList.Items.FindByValue("14").Selected = true;
                        else if (remainder <= TimeSpan.FromDays(31))
                            PinnedPostDropDownList.Items.FindByValue("30").Selected = true;
                        else if (remainder <= TimeSpan.FromDays(92))
                            PinnedPostDropDownList.Items.FindByValue("90").Selected = true;
                        else if (remainder <= TimeSpan.FromDays(183))
                            PinnedPostDropDownList.Items.FindByValue("180").Selected = true;
                        else if (remainder <= TimeSpan.FromDays(367))
                            PinnedPostDropDownList.Items.FindByValue("366").Selected = true;
                        else
                        {
                            if (remainder >= TimeSpan.FromDays(anouncementTsp.Days)) // this should be an anouncement
                                PinnedPostDropDownList.Items.FindByValue("999").Selected = true;
                        }
                    }

                    #endregion
                }

                if (IsLockedCheckBox != null)
                    IsLockedCheckBox.Checked = post.IsLocked;

                if (IsAnonymousPostCheckBox != null)
                    IsAnonymousPostCheckBox.Checked = post.IsAnonymousPost;

                if (PostIconRadioButtonList != null)
                    PostIconRadioButtonList.SelectedValue = post.EmoticonID.ToString();
            }

            #endregion

            #region Data binding (performed when not a postback)

            if (!Page.IsPostBack)
            {
                if (SubscribeToThreadCheckBox != null)
                {
                    if (csContext.User.IsAnonymous)
                    {
                        SubscribeToThreadCheckBox.Checked = false;
                        SubscribeToThreadCheckBox.Visible = false;
                    }
                    else
                        SubscribeToThreadCheckBox.Checked = csContext.User.EnableThreadTracking;
                }

                if (post == null && replyToPost != null && csContext.QueryString["Quote"] != null && csContext.QueryString["Quote"].ToLower() == "true")
                    this.PostBodyEditor.Text = "[quote user=\"" + replyToPost.User.DisplayName + "\"]" + replyToPost.RenderedBody(PostTarget.WebQuote) + "[/quote]";
            }

            #endregion

            #region Data binding

            if (post == null)
            {
                if (EditNotesBodyTextBox != null)
                    EditNotesBodyTextBox.Visible = false;

                if (CurrentEditNotesTextBox != null)
                    CurrentEditNotesTextBox.Visible = false;
            }

            if (ReplyToBodyText != null)
            {
                if (replyToPost != null)
                {
                    ReplyToBodyText.Text = string.Format("<div id=\"{0}__QuoteText\">{1}</div>", this.ClientID, replyToPost.RenderedBody(PostTarget.WebQuote));
                }
                else
                    ReplyToBodyText.Visible = false;
            }

            if (QuoteButton != null)
            {
                if (replyToPost != null && ReplyToBodyText != null && ReplyToBodyText.Visible)
                {
                    QuoteButton.Attributes["onclick"] = string.Format("{0}_Quote(); return false;", this.ClientID);
                    ForumControlUtility.Instance().RegisterStartupScript(this, typeof(CreateEditForumPostForm), this.ClientID + "_Quote",
                        string.Format("<script type=\"text/javascript\">\n// <![CDATA[\nfunction {1}_Quote()\n{{\n{0};\nvar quotableText = document.getElementById('{1}__QuoteText');\nvar content = Telligent_Common.GetSelectedHtmlInElement(quotableText,true,false,'{2}');\nif (content)\n{{\n{3};\n}}\n}}\n// ]]>\n</script>",
                        PostBodyEditor.GetBookmarkScript(),
                        this.ClientID,
                        JavaScript.Encode(ResourceManager.GetString("CreateeditPost_InvalidQuoteSelection")),
                        PostBodyEditor.GetContentInsertScript("'[quote user=\"" + JavaScript.Encode(replyToPost.User.DisplayName) + "\"]' + content + '[/quote]'")
                        ), false);
                }
                else
                    QuoteButton.Visible = false;
            }

            if (ReplyToAuthorText != null)
            {
                if (replyToPost != null)
                {
                    if (replyToPost.IsAnonymousPost && ForumConfiguration.Instance().EnableUserPostingAsAnonymous && forum.EnableAnonymousPostingForUsers)
                        ReplyToAuthorText.Text = ResourceManager.GetString("DefaultAnonymousUsername");
                    else
                        ReplyToAuthorText.Text = replyToPost.User.DisplayName;
                }
                else
                    ReplyToAuthorText.Visible = false;
            }

            if (IsAnonymousPostCheckBox != null)
            {
                if (!(ForumConfiguration.Instance().EnableUserPostingAsAnonymous && forum.EnableAnonymousPostingForUsers))
                {
                    IsAnonymousPostCheckBox.Checked = false;
                    IsAnonymousPostCheckBox.Visible = false;
                }
            }

            if (PinnedPostDropDownList != null)
            {
                if ((
                        csContext.User.IsForumAdministrator
                        || Permissions.ValidatePermissions(forum, Permission.Sticky, csContext.User)
                        || Moderate.CheckIfUserIsModerator(csContext.User.UserID, forum.SectionID)
                    )
                    && replyToPost == null)
                {
                    // Do we have an announcement?
                    if (Convert.ToInt32(PinnedPostDropDownList.SelectedItem.Value) == 999)
                    {
                        // Check it and show disabled
                        IsLockedCheckBox.Checked = true;
                        IsLockedCheckBox.Enabled = false;
                    }
                    else
                        IsLockedCheckBox.Enabled = true;
                }
                else
                    PinnedPostDropDownList.Visible = false;
            }

            if (RecipientsText != null && Recipient != null)
                RecipientsText.Text = Recipient.DisplayName;

            foreach (WrappedSubFormBase subForm in this.SubForms)
            {
                subForm.DataSource = this.DataSource;
                subForm.DataBind();
            }

            #endregion
        }

        #endregion

        #region Events

        void PinnedPostDropDownList_SelectedIndexChanged(object sender, EventArgs e)
        {
            EnsureChildControls();

            if (Convert.ToInt32(PinnedPostDropDownList.SelectedItem.Value) == 999)
            {
                // Check it and show disabled
                IsLockedCheckBox.Checked = true;
                IsLockedCheckBox.Enabled = false;
            }
            else if (!IsLockedCheckBox.Checked)
            {
                // Show it enabled and uncheck it only if wasn't checked before postback.
                IsLockedCheckBox.Checked = false;
                IsLockedCheckBox.Enabled = true;
            }
            else
            {
                // Just enable and keep it as it was before postback
                IsLockedCheckBox.Enabled = true;
            }
        }

        void SubmitButton_Click(object sender, EventArgs e)
        {
            if ((SubmitButton.CausesValidation && !Page.IsValid) || !this.IsValid())
                return;

            if (DataSource != null && ForumConfiguration.Instance().RequireEditNotes && !ForumControlUtility.Instance().IsValid(this.EditNotesValidationGroup, this.Page))
                return;

            foreach (WrappedSubFormBase subForm in this.SubForms)
            {
                if (!subForm.IsValid())
                    return;
            }

            CSContext csContext = ForumControlUtility.Instance().GetCurrentCSContext(this.Page);

            Thread post = PopulatePost();
            ForumPost newPost = SavePost(post);

            foreach (WrappedSubFormBase subForm in this.SubForms)
            {
                subForm.ApplyChangesAfterCommit(newPost);
            }

            if (csContext.PostID <= 0)
                csContext.PostID = newPost.PostID;

            if (!newPost.IsApproved)
            {
                if (this.ModeratedSuccessActions != null)
                    this.ModeratedSuccessActions.Execute(this, newPost);
            }
            else
            {
                if (this.UnmoderatedSuccessActions != null)
                    this.UnmoderatedSuccessActions.Execute(this, newPost);
            }
        }

        protected string Preview()
        {
            Thread post = PopulatePost();
            Posts.FormatPost(post);

            if (PreviewForumPostList != null)
            {
                List<ForumPost> posts = new List<ForumPost>();
                if (this.ReplyToPost != null)
                    posts.Add(this.ReplyToPost);

                posts.Add(post);

                PreviewForumPostList.DataSource = posts;
                PreviewForumPostList.DataBind();

                StringWriter stringWriter = new StringWriter();
                HtmlTextWriter htmlWriter = new HtmlTextWriter(stringWriter);
                PreviewForumPostList.RenderControl(htmlWriter, false);

                return stringWriter.ToString();
            }

            return string.Empty;
        }

        #region Helpers

        protected virtual ForumPost SavePost(Thread post)
        {
            ForumPost newPost;
            CSContext csContext = CSControlUtility.Instance().GetCurrentCSContext(this.Page);

            if (this.Forum.SectionID == 0)
            {
                // private message

                ArrayList recipients = new ArrayList();
                recipients.Add(csContext.User);
                recipients.Add(Recipient);

                if (post.PostID <= 0)
                    newPost = PrivateMessages.AddPrivateMessagePost(post, csContext.User, recipients);
                else
                {
                    PrivateMessages.AddRecipientsToExtendedAttributes(recipients, post);
                    Posts.UpdatePost(post, csContext.User.UserID);
                    PrivateMessages.AddRecipients(recipients, post);
                    newPost = Posts.GetPost(post.PostID, csContext.User.UserID, false, false, true);
                }
            }
            else if (post.PostID <= 0)
            {
                // Use the posts user so that any rules that were applied when populating
                // post user data are not lost.  If the post user object is null then use
                // the current user.
                if (post.User != null)
                    newPost = Posts.AddPost(post, post.User);
                else
                    newPost = Posts.AddPost(post, csContext.User);
            }
            else
            {
                Posts.UpdatePost(post, csContext.User.UserID);
                newPost = Posts.GetPost(post.PostID, csContext.User.UserID, false, false, true);
            }

            return newPost;
        }

        protected virtual Thread PopulatePost()
        {
            Thread post = null;

            Forum forum = this.Forum;
            CSContext csContext = ForumControlUtility.Instance().GetCurrentCSContext(this.Page);

            ForumPost editedPost = DataSource as ForumPost;
            if (editedPost != null)
            {
                post = new Thread();

                if (editedPost.PostID != editedPost.ParentID)
                {
                    post.ParentID = editedPost.ParentID;
                }

                post.PostID = editedPost.PostID;
                post.PostLevel = editedPost.PostLevel;
                post.SectionID = editedPost.SectionID;

                // Get initial post's posting date 
                post.PostDate = editedPost.PostDate;
                post.CopyPollDataFrom(editedPost);
                post.InkID = editedPost.InkID;

                // Get the current StickyDate
                Thread thread = Threads.GetThread(editedPost.ThreadID);
                post.IsSticky = thread.IsSticky;
                post.StickyDate = thread.StickyDate;

                post.Username = editedPost.Username;
                post.UserID = editedPost.UserID;
                post.IsIgnoredPost = editedPost.IsIgnoredPost;
                //TODO: Missing properties
                post.Categories = editedPost.Categories;
                post.FormattedBody = editedPost.FormattedBody;
                post.ParentID = editedPost.ParentID;
                post.SectionID = editedPost.SectionID;
                post.ThreadID = editedPost.ThreadID;
                post.ThreadDate = editedPost.ThreadDate;
                post.ThreadStartDate = editedPost.ThreadStartDate;
                post.ThreadStarterUsername = editedPost.ThreadStarterUsername;
                post.ThreadIDNext = editedPost.ThreadIDNext;
                post.ThreadIDPrev = editedPost.ThreadIDPrev;
                post.SortOrder = editedPost.SortOrder;
                post.Replies = editedPost.Replies;
                post.IsApproved = editedPost.IsApproved;
                post.AttachmentFilename = editedPost.AttachmentFilename;
                post.Views = editedPost.Views;
                post.HasRead = editedPost.HasRead;
                post.UserHostAddress = editedPost.UserHostAddress;
                post.PostMedia = editedPost.PostMedia;
                //post.PostConfigurationValue;
                //post.ApplicationPostTypeValue;
                post.Name = editedPost.Name;
                post.UserTime = editedPost.UserTime;
                post.SetSerializerData(editedPost.GetSerializerData());
                post.Points = editedPost.Points;
                post.TotalRatings = editedPost.TotalRatings;
                post.RatingSum = editedPost.RatingSum;
                post.PostStatus = editedPost.PostStatus;
                post.SpamScore = editedPost.SpamScore;
            }

            if (post == null)
            {
                post = new Thread();
                post.SectionID = forum.SectionID;

                if (this.ReplyToPost != null)
                    post.ParentID = this.ReplyToPost.PostID;
                else
                    post.ParentID = 0;

                post.PostDate = DateTime.Now;

                post.Username = csContext.User.Username;
                post.UserID = csContext.User.UserID;
                post.IsIgnoredPost = csContext.User.IsIgnored;
            }

            post.Body = PostBodyEditor.Text;
            post.PostType = PostBodyEditor.IsRichTextCapable ? PostContentType.HTML : PostContentType.Text;
            post.Subject = PostSubjectTextBox.Text;

            if (IsLockedCheckBox != null)
                post.IsLocked = IsLockedCheckBox.Checked;

            if (SubscribeToThreadCheckBox != null && this.Forum.SectionID != 0)
                post.IsTracked = SubscribeToThreadCheckBox.Checked;
            else
                post.IsTracked = false;

            if (IsAnonymousPostCheckBox != null && (ForumConfiguration.Instance().EnableUserPostingAsAnonymous && forum.EnableAnonymousPostingForUsers) &&
                    (CSContext.Current.SiteSettings.EnableAnonymousUserPosting && forum.EnableAnonymousPosting))
                post.IsAnonymousPost = IsAnonymousPostCheckBox.Checked;
            else
                post.IsAnonymousPost = false;

            if (post.IsAnonymousPost)
            {
                User anonUser = Users.GetAnonymousUser();
                post.AuthorID = post.UserID;

                if (Globals.IsNullorEmpty(post.GetExtendedAttribute("AuthorID")))
                    post.SetExtendedAttribute("AuthorID", post.AuthorID.ToString());
                post.Username = anonUser.Username;
                post.UserID = anonUser.UserID;
            }

            if (PostIconRadioButtonList != null && !string.IsNullOrEmpty(PostIconRadioButtonList.SelectedValue))
                post.EmoticonID = int.Parse(PostIconRadioButtonList.SelectedValue);

            if (EditNotesBodyTextBox != null)
            {
                string[] editItems = new string[4];
                editItems[0] = csContext.User.DisplayName;
                editItems[1] = DateTime.Now.ToString(csContext.SiteSettings.TimeFormat);
                editItems[2] = csContext.SiteSettings.TimezoneOffset.ToString();
                editItems[3] = DateTime.Now.ToString(csContext.SiteSettings.DateFormat);

                string editNotes = "\n" + EditNotesBodyTextBox.Text;
                if (!string.IsNullOrEmpty(post.EditNotes))
                    editNotes += "\n\n" + post.EditNotes;

                post.EditNotes = Formatter.EditNotes(String.Format(csContext.Context.Server.HtmlDecode(ResourceManager.GetString("CreateEditPost_EditNotesRecord")), editItems) + editNotes);
            }

            if (Permissions.ValidatePermissions(forum, Permission.Sticky, csContext.User))
            {
                if (PinnedPostDropDownList != null && Convert.ToInt32(PinnedPostDropDownList.SelectedItem.Value) > 0)
                {
                    post.IsSticky = true;

                    switch (Convert.ToInt32(PinnedPostDropDownList.SelectedItem.Value))
                    {
                        case 1:
                            post.StickyDate = DateTime.Now.Date.AddDays(1); break;
                        case 3:
                            post.StickyDate = DateTime.Now.Date.AddDays(3); break;
                        case 7:
                            post.StickyDate = DateTime.Now.Date.AddDays(7); break;
                        case 14:
                            post.StickyDate = DateTime.Now.Date.AddDays(14); break;
                        case 30:
                            post.StickyDate = DateTime.Now.Date.AddMonths(1); break;
                        case 90:
                            post.StickyDate = DateTime.Now.Date.AddMonths(3); break;
                        case 180:
                            post.StickyDate = DateTime.Now.Date.AddMonths(6); break;
                        case 366:
                            post.StickyDate = DateTime.Now.Date.AddYears(1); break;
                        case 999:
                            post.StickyDate = DateTime.Now.Date.AddYears(25); break;
                    }
                }
                else
                {
                    // Was it previously sticky?
                    if (post.IsSticky)
                    {
                        // Not sticky by now
                        post.IsSticky = false;
                        post.StickyDate = post.PostDate;
                    }
                }
            }

            if (ForumConfiguration.Instance().EnableThreadStatus && forum.EnableThreadStatus)
                post.Status = forum.DefaultThreadStatusValue;

            foreach (WrappedSubFormBase subForm in this.SubForms)
            {
                subForm.ApplyChangesBeforeCommit(post);
            }

            return post;
        }

        #endregion

        #endregion

        #region Callback Implementation

        private string _callbackArgument = null;

        public void RaiseCallbackEvent(string eventArgument)
        {
            _callbackArgument = eventArgument;
        }

        public string GetCallbackResult()
        {
            if (_callbackArgument == null)
                return string.Empty;

            EnsureChildControls();

            switch (_callbackArgument)
            {
                case "preview":
                    return Preview();
            }

            return string.Empty;
        }

        public string GetPreviewScript(string callbackScript)
        {
            EnsureChildControls();

            if (this.PreviewForumPostList != null)
                return "document.getElementById('" + this.PreviewForumPostList.ContainerId + "').innerHTML=''; __theFormPostData = ''; __theFormPostCollection = new Array(); WebForm_InitCallback(); " + Page.ClientScript.GetCallbackEventReference(this, "'preview'", "new Function('result', 'document.getElementById(\\'" + this.PreviewForumPostList.ContainerId + "\\').innerHTML=result;" + JavaScript.Encode(callbackScript ?? "") + "')", "");
            else
                return string.Empty;
        }

        #endregion

        protected virtual void AccessCheck(Forum forum, User user, ForumPost post, ForumPost replyToPost)
        {
            if (forum.SectionID == 0)
            {
                if (user.IsAnonymous || Recipient == null || Recipient.IsAnonymous)
                    ForumPermission.RedirectOrException(CSExceptionType.AccessDenied);

                Users.ValidateUserAccess(this.Recipient, user);
            }
            else
            {
                if (post != null && post.PostID > 0)
                    Permissions.AccessCheck(forum, Permission.Edit, user, post);
                if (replyToPost != null)
                    Permissions.AccessCheck(forum, Permission.Reply, user, replyToPost);
                else
                    Permissions.AccessCheck(forum, Permission.Post, user);
            }
        }
    }
}
